import { decode, encode } from "cbor-x";

export const baseURL = window.location.origin;

const HEADER_RESP = "resp";
const RESP_OK = "ok";
const RESP_FAIL = "fail";
const RESP_PANIC = "panic";

export interface ErrInfo {
    err_code: number,
    err_msg: string,
}

async function parseResp(resp: Response) {
    resp.headers
    if (resp.status != 200) {
        throw `http错误:${resp.statusText}`;
    }
    const head = resp.headers.get(HEADER_RESP);
    if (head == null) {
        throw 'http响应错误';
    }
    const body = new Uint8Array(await resp.arrayBuffer());
    if (head == RESP_OK) {
        return new ServiceResponse(body, resp.headers);
    } else if (head == RESP_FAIL) {
        const err = decode(body) as ErrInfo;
        throw `执行失败:${err.err_code} ${err.err_msg}`
    } else if (head == RESP_PANIC) {
        throw '无法处理的错误';
    }
    throw `http未知错误`;
}

class ServiceResponse {

    body: Uint8Array;
    headers: Headers;

    constructor(body: Uint8Array, headers: Headers) {
        this.body = body;
        this.headers = headers;
    }

    parse<T>() {
        return decode(this.body) as T;
    }
}

class Service {

    readonly baseURL: string;

    constructor(baseURL: string) {
        this.baseURL = baseURL;
    }

    async get(url: string) {
        const resp = await fetch(this.makeUrl(url), {
            method: 'GET'
        });
        return await parseResp(resp);
    }

    async post<T>(url: string, body: Uint8Array | null | T = null) {
        let data: Uint8Array | null = null;
        if (body instanceof Uint8Array) {
            data = body;
        } else if (body == null) {
        } else {
            data = encode(body);
        };
        
        const resp = await fetch(this.makeUrl(url), {
            method: 'POST',
            body: data
        });
        const respBody = await parseResp(resp);
        return respBody;
    }

    private makeUrl(url: string) {
        return `${baseURL}${this.baseURL}${url}`
    }
}

export const system = new Service("/api/system");
export const cp = new Service('/api/cp');
export const cargo = new Service("/api/cp/cargo");
export const drop = new Service("/api/cp/drop");
export const heat = new Service("/api/cp/heat");
